package learn_effective_java.item_02.nutritionfacts;
/*
 * Luckily, there is a third alternative 
 * that combines the safety of the telescoping constructor pattern 
 * with the readability of the JavaBeans pattern.
 * 
 * It is a form of the Builder Pattern.
 * Instead of making the desired object directly, 
 * the client calls a constructor(or static factory) with all of 
 * the required parameters and gets a builder object.
 * 
 * Then the client calls setter-like methods on the builder object 
 * to set each optional parameter of interest.
 * Finally, the client calls a parameterless build method to generate the object, 
 * which is typically immutable.
 * The builder is typically a static member class of the class it builds.
 * Here's how it looks in practice:
 * 
 */

public class NutritionFacts3 {
	private final int servingSize;
	private final int servings;
	private final int calories;
	private final int fat;
	private final int sodium;
	private final int carbohydrate;

	private NutritionFacts3(Builder builder) {
		this.servingSize = builder.servingSize;
		this.servings = builder.servings;
		this.calories = builder.calories;
		this.fat = builder.fat;
		this.sodium = builder.sodium;
		this.carbohydrate = builder.carbohydrate;
	}

	@Override
	public String toString() {
		return "NutritionFacts3 [servingSize=" + servingSize + ", servings=" + servings + ", calories=" + calories
				+ ", fat=" + fat + ", sodium=" + sodium + ", carbohydrate=" + carbohydrate + "]";
	}

	public static class Builder {
		// Required parameters
		private final int servingSize;
		private final int servings;
		// Optional parameters - initialized to default values
		private int calories = 0;
		private int fat = 0;
		private int sodium = 0;
		private int carbohydrate = 0;

		public Builder(int servingSize, int servings) {
			this.servingSize = servingSize;
			this.servings = servings;
		}

		public Builder calories(int val) {
			this.calories = val;
			return this;
		}

		public Builder fat(int val) {
			this.fat = val;
			return this;
		}

		public Builder sodium(int val) {
			this.sodium = val;
			return this;
		}

		public Builder carbohydrate(int val) {
			this.carbohydrate = val;
			return this;
		}

		public NutritionFacts3 build() {
			// validity checks
			// check parameters
			if (servingSize <= 0) {
				throw new IllegalArgumentException(servingSize + " is illegal");
			}
			return new NutritionFacts3(this);
		}
	}
}
